package com.md.common.utils.file;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(ZipUtils.class);

	private ZipUtils() {
		super();
	}

	public static void main(String[] args) {
		compress("D:\\images\\0001\\01071551", new File("D:\\soft\\BvSshClient-Inst.exe"), "D:\\images\\0001\\01071551-zip.zip");
	}

	public static void compress(String filePath, File otherFile, String zipPath) {

		try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipPath));
			 BufferedOutputStream bos = new BufferedOutputStream(out)) {

			File sourceFile = new File(filePath);
			compress(out, bos, otherFile, otherFile.getName());
			compress(out, bos, sourceFile, sourceFile.getName());

		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

    /**
     * 压缩文件/目录
     * @param filePath 源文件/目录（全路径）
     * @param zipPath 目标zip文件（全路径）
     */
    public static void compress(String filePath, String zipPath) {

        try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipPath));
             BufferedOutputStream bos = new BufferedOutputStream(out)) {

            File sourceFile = new File(filePath);
            compress(out, bos, sourceFile, sourceFile.getName());

        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    private static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) throws Exception {
        // 如果路径为目录（文件夹）
        if (sourceFile.isDirectory()) {
            // 取出文件夹中的文件（或子文件夹）
            File[] flist = sourceFile.listFiles();
            if (flist.length == 0) {// 如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
                out.putNextEntry(new ZipEntry(base + "/"));
            } else {// 如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
                for (int i = 0; i < flist.length; i++) {
                    compress(out, bos, flist[i], base + "/" + flist[i].getName());
                }
            }
        } else {// 如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
            out.putNextEntry(new ZipEntry(base));
            try (FileInputStream fos = new FileInputStream(sourceFile);
                 BufferedInputStream bis = new BufferedInputStream(fos)) {
                int buffer;
                // 将源文件写入到zip文件中
                while ((buffer = bis.read()) != -1) {
                    bos.write(buffer);
                }
            }
            out.closeEntry();
        }
    }

}
